import 'package:flutter/material.dart';


/// 
/// ## FutureBuilder
///
/// FutureBuilder会依赖一个Future，它会根据所依赖的Future的状态来动态构建自身。我们看一下FutureBuilder构造函数：
/// 
/// ```
/// FutureBuilder({
///   this.future,
///   this.initialData,
///   @required this.builder,
/// })
/// ```
/// 
/// - future：FutureBuilder依赖的Future，通常是一个异步耗时任务。
/// 
/// - initialData：初始数据，用户设置默认数据。
/// 
/// - builder：Widget构建器；该构建器会在Future执行的不同阶段被多次调用，构建器签名如下：
///       `Function (BuildContext context, AsyncSnapshot snapshot)`
///   snapshot会包含当前异步任务的状态信息及结果信息 ，比如我们可以通过snapshot.connectionState获取异步任务的状
///   态信息、通过snapshot.hasError判断异步任务是否有错误等等，完整的定义读者可以查看AsyncSnapshot类定义。
/// 
/// 另外，FutureBuilder的builder函数签名和StreamBuilder的builder是相同的。
/// 
/// 
/// ## StreamBuilder
/// 
/// 我们知道，在Dart中Stream 也是用于接收异步事件数据，和Future 不同的是，它可以接收多个异步操作的结果，它常用于会多
/// 次读取数据的异步任务场景，如网络内容下载、文件读写等。StreamBuilder正是用于配合Stream来展示流上事件（数据）变化
/// 的UI组件。下面看一下StreamBuilder的默认构造函数：
/// 
/// ```
/// StreamBuilder({
///   Key key,
///   this.initialData,
///   Stream<T> stream,
///   @required this.builder,
/// })
/// ```
/// 
/// 可以看到和FutureBuilder的构造函数只有一点不同：前者需要一个future，而后者需要一个stream。



class AsyncBuilderPage extends StatelessWidget {

  Future<String> mockNetworkData() async {
    return Future.delayed(Duration(seconds: 2), () => "Data From Neteork");
  }

  Stream<int> counter() {
    return Stream.periodic(Duration(seconds: 1), (i) {
      return i;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Future Builder"),
      ),
      body: Flex(
        direction: Axis.vertical,
        children: <Widget>[
          Expanded(
            flex: 1,
            child: Center(
              child: FutureBuilder<String>(
                future: mockNetworkData(),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.done) {
                    if (snapshot.hasError) {
                      return Text("Error: ${snapshot.error}");
                    } else {
                      return Text("Contents: ${snapshot.data}");
                    }
                  } else {
                    return CircularProgressIndicator();
                  }
                },
              )
            ),
          ),
          Expanded(
            flex: 1,
            child: Center(
              child: StreamBuilder<int>(
                stream: counter(),
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return Text("Error: ${snapshot.error}");
                  }

                  switch (snapshot.connectionState) {
                    case ConnectionState.none:
                      return Text("No Stream");
                    case ConnectionState.waiting:
                      return Text("Waiting ...");
                    case ConnectionState.active:
                      return Text("Active: ${snapshot.data}");
                    case ConnectionState.done:
                      return Text("Stream Closed");
                  }

                  return null;
                },
              ),
            ),
          )
        ],
      )
    );
  }
}